"""
通知相关的Celery任务
"""

from datetime import datetime
import asyncio
from typing import List, Dict, Any, Optional
from sqlalchemy.orm import Session

from app.celery_app import celery_app
from app.database import SessionLocal
from app.models import NotifyLog
from app.models.notify_log_product import NotifyLogProduct
from app.utils.logger import get_monitor_logger
# 延迟导入 wechat_service，避免 Celery Beat 启动时初始化微信服务
# from app.services.wechat_service import wechat_service
from app.services.notification_service import NotificationService


# send_email_notification 任务已废弃并移除
# 请使用 NotificationService 或 create_notify_logs_batch 替代


# send_product_notification 任务已废弃并移除
# 请使用 NotificationService 或 create_notify_logs_batch 替代


# batch_send_notifications 任务已废弃并移除
# 请使用 create_notify_logs_batch 替代


# _build_product_email_content 函数已废弃并移除
# 邮件内容构建已迁移到 NotificationService


@celery_app.task(queue="notification", bind=True, max_retries=3)
def create_notify_logs_batch(self, user_id: int, monitor_id: int, keyword: str,
                           products: List[Dict[str, Any]], email_success: bool, monitor_type: str = "keyword") -> Dict[str, Any]:
    """
    异步批量创建通知日志记录

    Args:
        user_id: 用户ID
        monitor_id: 监控任务ID
        keyword: 监控关键词
        products: 商品列表
        email_success: 邮件发送是否成功

    Returns:
        Dict: 执行结果
    """
    logger = get_monitor_logger()

    try:
        db = SessionLocal()

        if email_success and products:
            # 成功发送邮件，创建成功记录
            notify_log = NotifyLog.create_from_products(
                user_id=user_id,
                monitor_id=monitor_id,
                products=products,
                success=True,
                channel="EMAIL",
                monitor_type=monitor_type
            )
            db.add(notify_log)
            db.commit()
            db.refresh(notify_log)  # 获取新创建的记录ID

            # 批量创建商品明细记录
            product_records = NotifyLogProduct.create_batch_from_products(
                notify_log_id=notify_log.id,
                products=products,
                monitor_type=monitor_type
            )
            db.add_all(product_records)
            db.commit()

            logger.info(f"✅ 通知日志及商品明细入库成功: 用户{user_id}, 监控{monitor_id}, 商品数{len(products)}, 明细记录{len(product_records)}条")

            return {
                "status": "success",
                "user_id": user_id,
                "monitor_id": monitor_id,
                "product_count": len(products),
                "records_created": 1,
                "product_records_created": len(product_records)
            }
        else:
            # 邮件发送失败，创建失败记录
            error_msg = "邮件发送失败" if not email_success else "无商品数据"
            notify_log = NotifyLog.create_failure_log(
                user_id=user_id,
                monitor_id=monitor_id,
                product_count=len(products) if products else 0,
                error_msg=error_msg,
                channel="EMAIL"
            )
            db.add(notify_log)
            db.commit()

            logger.warning(f"⚠️ 通知失败日志入库: 用户{user_id}, 监控{monitor_id}, 原因: {error_msg}")

            return {
                "status": "failed",
                "user_id": user_id,
                "monitor_id": monitor_id,
                "product_count": len(products) if products else 0,
                "error": error_msg,
                "records_created": 1
            }

    except Exception as exc:
        logger.error(f"❌ 通知日志入库异常: 用户{user_id}, 监控{monitor_id}, 错误: {exc}")

        # 重试机制
        if self.request.retries < self.max_retries:
            logger.info(f"🔄 重试通知日志入库: 第{self.request.retries + 1}次")
            raise self.retry(countdown=60 * (self.request.retries + 1), exc=exc)
        else:
            logger.error(f"💥 通知日志入库最终失败: 用户{user_id}, 监控{monitor_id}")
            return {
                "status": "error",
                "user_id": user_id,
                "monitor_id": monitor_id,
                "error": str(exc),
                "records_created": 0
            }
    finally:
        if 'db' in locals():
            db.close()


@celery_app.task(queue="notification", bind=True, max_retries=3)
def send_notification_with_log(self, user_id: int, monitor_id: int, products: List[Dict[str, Any]],
                               notification_subject: str, monitor_type: str = "keyword",
                               channel: str = "EMAIL", user_openid: Optional[str] = None,
                               user_tg: Optional[str] = None, user_email: Optional[str] = None) -> Dict[str, Any]:
    """
    统一的通知任务：创建日志 -> 发送通知 -> 更新状态
    支持所有渠道（EMAIL/WECHAT/TG），微信通知支持小程序跳转
    
    Args:
        user_id: 用户ID
        monitor_id: 监控任务ID
        products: 商品列表
        notification_subject: 通知主题
        monitor_type: 监控类型
        channel: 通知渠道（EMAIL/WECHAT/TG）
        user_openid: 用户微信OpenID（微信渠道必需）
        user_tg: 用户Telegram ID（TG渠道必需）
        user_email: 用户邮箱（邮件渠道必需）
        
    Returns:
        Dict: 执行结果
    """
    logger = get_monitor_logger()
    db = None
    notify_log = None
    
    try:
        logger.info(f"📢 统一通知流程开始: 用户{user_id}, 监控{monitor_id}, 渠道{channel}, 商品{len(products)}个")
        
        if not products:
            logger.warning(f"⚠️ 商品列表为空: 用户{user_id}, 监控{monitor_id}")
            return {
                "status": "failed",
                "error": "商品列表为空",
                "notify_log_id": None,
                "channel": channel
            }
        
        db = SessionLocal()
        
        # 步骤1: 创建通知日志记录
        logger.info(f"🔄 步骤1: 创建{channel}通知日志记录...")
        notify_log = NotifyLog.create_from_products(
            user_id=user_id,
            monitor_id=monitor_id,
            products=products,
            success=False,  # 初始状态为待发送
            channel=channel,
            monitor_type=monitor_type
        )
        db.add(notify_log)
        db.commit()
        db.refresh(notify_log)
        
        notify_log_id = notify_log.id
        logger.info(f"✅ 通知日志创建成功: notify_log_id={notify_log_id}, 渠道={channel}")
        
        # 创建商品明细记录
        product_records = NotifyLogProduct.create_batch_from_products(
            notify_log_id=notify_log_id,
            products=products,
            monitor_type=monitor_type
        )
        db.add_all(product_records)
        db.commit()
        
        # 步骤2: 根据渠道发送通知
        logger.info(f"🔄 步骤2: 发送{channel}通知...")
        
        # 初始化变量，防止None错误
        notification_success = False
        error_message = None
        
        try:
            # 在事件循环中运行异步操作
            import asyncio
            
            async def send_notification():
                if channel == 'WECHAT':
                    # 微信通知（支持小程序跳转）
                    # 延迟导入，避免 Celery Beat 启动时初始化微信服务
                    from app.services.wechat_service import wechat_service as _wechat_service
                    return await _wechat_service.send_product_notification(
                        openid=user_openid or "test_openid",
                        products=products,
                        notification_subject=notification_subject,
                        monitor_type=monitor_type,
                        notify_log_id=notify_log_id  # 🎯 关键：支持小程序跳转
                    )
                elif channel == 'EMAIL':
                    # 邮件通知
                    notification_service = NotificationService()
                    return await notification_service.send_product_notification(
                        user_email=user_email or "test@example.com",
                        products=products,
                        notification_subject=notification_subject,
                        monitor_type=monitor_type
                    )
                elif channel == 'TG':
                    # Telegram通知
                    notification_service = NotificationService()
                    return await notification_service.send_telegram_notification(
                        user_tg=user_tg or "test_tg",
                        products=products,
                        notification_subject=notification_subject,
                        monitor_type=monitor_type
                    )
                else:
                    logger.error(f"❌ 不支持的通知渠道: {channel}")
                    return False
            
            # 运行异步通知发送
            try:
                loop = asyncio.get_event_loop()
                notification_success = loop.run_until_complete(send_notification())
                # 确保返回值不为None
                if notification_success is None:
                    logger.warning(f"⚠️ {channel}通知服务返回了None，默认为失败")
                    notification_success = False
            except RuntimeError:
                # 如果没有事件循环，创建新的
                loop = asyncio.new_event_loop()
                asyncio.set_event_loop(loop)
                try:
                    notification_success = loop.run_until_complete(send_notification())
                    # 确保返回值不为None
                    if notification_success is None:
                        logger.warning(f"⚠️ {channel}通知服务返回了None，默认为失败")
                        notification_success = False
                finally:
                    loop.close()
            
            logger.info(f"📢 {channel}通知发送结果: {'成功' if notification_success else '失败'}")
            
        except Exception as send_error:
            logger.error(f"❌ {channel}通知发送异常: {send_error}")
            notification_success = False
            error_message = str(send_error)
        
        # 步骤3: 更新通知日志状态
        logger.info(f"🔄 步骤3: 更新通知日志状态...")
        notify_log.success = notification_success
        if not notification_success:
            notify_log.error_msg = (error_message or f"{channel}通知发送失败")[:300]
        
        db.commit()
        
        result = {
            "status": "success" if notification_success else "failed",
            "notify_log_id": notify_log_id,
            "user_id": user_id,
            "monitor_id": monitor_id,
            "product_count": len(products),
            "channel": channel,
            "notification_success": notification_success
        }
        
        # 微信通知成功时添加小程序跳转URL
        if channel == 'WECHAT' and notification_success:
            result["miniprogram_url"] = f"/pages/notify-detail/notify-detail?logId={notify_log_id}"
        
        logger.info(f"✅ 统一通知流程完成: 渠道={channel}, notify_log_id={notify_log_id}, 成功={notification_success}")
        return result
        
    except Exception as exc:
        logger.error(f"❌ 统一通知流程异常: 用户{user_id}, 监控{monitor_id}, 渠道={channel}, 错误: {exc}")
        
        # 如果创建了日志但发送失败，更新为失败状态
        if notify_log and db:
            try:
                notify_log.success = False
                notify_log.error_msg = str(exc)[:300]
                db.commit()
            except Exception:
                pass
        
        # 重试机制
        if self.request.retries < self.max_retries:
            logger.info(f"🔄 重试统一通知流程: 第{self.request.retries + 1}次")
            raise self.retry(countdown=60 * (self.request.retries + 1), exc=exc)
        else:
            logger.error(f"💥 统一通知流程最终失败: 用户{user_id}, 监控{monitor_id}")
            return {
                "status": "error",
                "error": str(exc),
                "notify_log_id": notify_log.id if notify_log else None,
                "channel": channel
            }
    finally:
        if db:
            db.close()
